﻿using System;
using System.ComponentModel.Composition;
using System.Linq.Expressions;

namespace Fuse8.ContentManagementFramework.BizFacade.Services.Contents.Queryable
{
    public abstract class BaseArgumentOperation : ISupportedQueryableOperation
    {
        public abstract string Name { get; }

        public virtual bool IsNonQuery
        {
            get { return false; }
        }

        public virtual Func<MethodCallExpression, Expression> Converter { get { return p => p.Arguments[1]; } }
        public abstract Action<CmsContentQueryBuilder, Expression> BuidAction { get; }
    }

    [CmsQueryableOperation]
    public class WhereOperation:BaseArgumentOperation
    {
        public override string Name
        {
            get { return "Where"; }
        }
        public override Action<CmsContentQueryBuilder, Expression> BuidAction
        {
            get { return (b, e) => b.SetWhere(e); }
        }
    }

    [CmsQueryableOperation]
    public class SkipOperation : BaseArgumentOperation
    {
        public override string Name
        {
            get { return "Skip"; }
        }
        public override Action<CmsContentQueryBuilder, Expression> BuidAction
        {
            get { return (b, e) => b.SetSkip(e); }
        }
    }

    [CmsQueryableOperation]
    public class TakeOperation : BaseArgumentOperation
    {
        public override string Name
        {
            get { return "Take"; }
        }

        public override Action<CmsContentQueryBuilder, Expression> BuidAction
        {
            get { return (b, e) => b.SetTake(e); }
        }
    }

    [CmsQueryableOperation]
    public class OrderByOperation : BaseArgumentOperation
    {
        public override string Name
        {
            get { return "OrderBy"; }
        }
        public override Action<CmsContentQueryBuilder, Expression> BuidAction
        {
            get { return (b, e) => b.SetOrder(e, false); }
        }
    }

    [CmsQueryableOperation]
    public class OrderByDescendingOperation : BaseArgumentOperation
    {
        public override string Name
        {
            get { return "OrderByDescending"; }
        }
        public override Action<CmsContentQueryBuilder, Expression> BuidAction
        {
            get { return (b, e) => b.SetOrder(e, true); }
        }
    }

    [CmsQueryableOperation]
    public class CountOperation : BaseArgumentOperation
    {
        public override string Name
        {
            get { return "Count"; }
        }

        public override Func<MethodCallExpression, Expression> Converter
        {
            get { return p => null; }
        }
        public override Action<CmsContentQueryBuilder, Expression> BuidAction
        {
            get { return (b, e) => b.SelectCount(true); }
        }
        public override bool IsNonQuery
        {
            get { return true; }
        }
    }

    [CmsQueryableOperation]
    public class JoinContentOperation:BaseArgumentOperation
    {
        public override string Name
        {
            get { return "JoinContent"; }
        }
        public override Action<CmsContentQueryBuilder, Expression> BuidAction
        {
            get { return (b, e) => b.SetJoinContent(e); }
        }
        public override Func<MethodCallExpression, Expression> Converter
        {
            get { return p => p; }
        }
    }

    [CmsQueryableOperation]
    public class JoinWithOperation : BaseArgumentOperation
    {
        public override string Name
        {
            get { return "JoinWith"; }
        }
        public override Action<CmsContentQueryBuilder, Expression> BuidAction
        {
            get { return (b, e) => b.SetJoinWith(e); }
        }
        public override Func<MethodCallExpression, Expression> Converter
        {
            get { return p => p; }
        }
    }

    [CmsQueryableOperation]
    public class SelectPropertiesOperation : BaseArgumentOperation
    {
        public override string Name
        {
            get { return "SelectProperties"; }
        }

        public override Action<CmsContentQueryBuilder, Expression> BuidAction
        {
            get { return (b, e) => b.SetSelect(e); }
        }
    }

}